package com.smartcommunity.service.dataImport;

import com.smartcommunity.base.bean.ExceptionCode;
import com.smartcommunity.base.common.DataImport;
import com.smartcommunity.controller.DataImportBase;
import com.smartcommunity.dao.village.VillageDao;
import com.smartcommunity.entity.village.OrganizationVillage;
import com.smartcommunity.exception.BusinessException;
import com.smartcommunity.log.interceptor.Log;
import com.smartcommunity.service.dataImport.model.VillageOrgExportModel;
import com.smartcommunity.service.village.impl.VillageServiceImpl;
import com.smartcommunity.utils.BeanMapUtil;
import com.smartcommunity.utils.ToolPinyin;
import com.smartcommunity.utils.ToolString;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * 导入行政区划
 */
@Component("villageOrg")
@Slf4j
public class VillageOrgImport extends DataImportBase implements DataImport {

    @Autowired
    private VillageDao villageDao;
    @Autowired
    private VillageServiceImpl villageService;

    /**
     * 内容标题
     */
    private  String[] headerTitle = new String[]{
            "行政区划编号",
            "行政区划名称",
            "自定义上级行政区划编号",
            "系统中已存在的上级行政区划编号",
            "经度",
            "纬度"
    };

    /**
     * 错误信息
     */
    private  String[] headerErrorMsg = new String[]{
            "行政区划编号必须是数字",
            "行政区划名称不可为空",
            "第三列与第四列不可同时存在值",
            "第三列与第四列不可同时为空",
            "行政区划编号在系统中不存在"
    };

    /**
     * key taskId,value progress
     */
    final int cacheSize = 100000;
    Map<String, Integer> progressTag = new LinkedHashMap<String, Integer>((int) Math.ceil(cacheSize / 0.75f) + 1, 0.75f, true) {
        @Override
        protected boolean removeEldestEntry(Map.Entry<String, Integer> eldest) {
            return size() > cacheSize;
        }
    };

    @Transactional
    @Override
    @Log(info = "行政区划模板导入")
    public String importData(List list, String villageCode,String fileName, String taskId,HttpServletResponse response) throws IllegalArgumentException, BusinessException {
        progressTag.put(taskId,10);
        List<OrganizationVillage> insertList = new ArrayList<>();
        List<Object[]> objList = (List<Object[]>) list;
        //存储错误信息
        List<VillageOrgExportModel> dataListCopy = new ArrayList<>();
        OrganizationVillage orgBean;
        int errorCount = 0;
        int size = objList.size();
        for (int i = 0; i < size; i++) {
            boolean isError = false;
            Object[] objects = objList.get(i);
            StringBuffer errorMessages = new StringBuffer();
            // 行政区划编号
            String orgCode = String.valueOf(objects[0]) == "null" ? "" : String.valueOf(objects[0]);
            if (StringUtils.isBlank(orgCode)) {
                continue;//行政区划编号为空的数据直接放弃
                /*throw new BusinessException(ExceptionCode.EQUIPMENT_VILLAGE_ORG_IMPORT_EXCEPTION_CODE,
                        "第" + (i + Constant.START_ROW) + "行,行政区划编号不可为空!");*/
            }
            if (!ToolString.isNumeric(orgCode)) {
                String errorMsg = appendErrorMsg(headerTitle[0], orgCode, headerErrorMsg[0]);
                errorMessages.append(errorMsg);
                isError = true;
            }
            if (StringUtils.isNotEmpty(objects[2].toString()) && StringUtils.isNotEmpty(objects[3].toString())) {
                String errorMsg = appendErrorMsg(headerTitle[2], orgCode, headerErrorMsg[2]);
                errorMessages.append(errorMsg);
                isError = true;
            }
            // 行政区划名称
            String orgName = String.valueOf(objects[1]) == "null" ? "" : String.valueOf(objects[1]);
            if (StringUtils.isBlank(orgName)) {
                String errorMsg = appendErrorMsg(headerTitle[1], orgCode, headerErrorMsg[1]);
                errorMessages.append(errorMsg);
                isError = true;
            }
            orgBean = new OrganizationVillage();
            orgBean.setOrgCode(orgCode);
            orgBean.setOrgName(orgName);
            orgBean.setPinyin(ToolPinyin.getPinYinHeadChar(orgBean.getOrgName()));

            // 自定义上级行政区划编号
            String selfParentCode = String.valueOf(objects[2]) == "null" ? "" : String.valueOf(objects[2]);
            // 数据库中已存在的上级行政区划编号
            String DBParentCode = String.valueOf(objects[3]) == "null" ? "" : String.valueOf(objects[3]);
            if (StringUtils.isEmpty(selfParentCode) && StringUtils.isEmpty(DBParentCode)) {
                String errorMsg = appendErrorMsg(headerTitle[2], orgCode, headerErrorMsg[3]);
                errorMessages.append(errorMsg);
                isError = true;
            } else {
                //如果没填DBParentCode  则按照自定义上级编号生成数据
                if (StringUtils.isEmpty(DBParentCode)) {
                    //这里设置parentName用于数据插入之后生成ID  再更新parentId
                    if (selfParentCode.equals("-1")) {
                        orgBean.setParentId(-1);
                        orgBean.setParentName("-1");
                    } else {
                        orgBean.setParentId(0);//由于数据insert之前没有生成ID  这里先用0  之后再更新
                        orgBean.setParentName(selfParentCode);
                    }
                } else {
                    //根据DBParentCode查出对应的数据库自增id
                    Integer parenId = villageDao.getOrgIdByCode(DBParentCode);
                    if (parenId == null) {
                        String errorMsg = appendErrorMsg(headerTitle[3], orgCode, headerErrorMsg[4]);
                        errorMessages.append(errorMsg);
                        isError = true;
                    }
                    orgBean.setParentId(parenId);
                    orgBean.setParentName("dbparent");
                }
            }

            // 经度、纬度
            String lon = String.valueOf(objects[4]) == "null" ? "" : String.valueOf(objects[4]);
            String lat = String.valueOf(objects[5]) == "null" ? "" : String.valueOf(objects[5]);
            if (StringUtils.isNotEmpty(lon) && StringUtils.isNotEmpty(lat)) {
                orgBean.setMapCenter(lon + "," + lat);
            }
            if(isError){
                errorCount++;
                VillageOrgExportModel exportModel = new VillageOrgExportModel();
                exportModel.setOrgCode(orgCode);
                exportModel.setOrgName(orgName);
                exportModel.setSelfParentCode(selfParentCode);
                exportModel.setDBParentCode(DBParentCode);
                exportModel.setLon(lon);
                exportModel.setLat(lat);
                exportModel.setErrorMsg(errorMessages.toString());
                dataListCopy.add(exportModel);
            }else {
                insertList.add(orgBean);
            }
        }

        try {
            progressTag.put(taskId,20);
            //查出现在数据库中所有行政区划code   数据库已存在该orgCode  则移除
            List<String> existOrgCodes = villageDao.getAllOrgCode();
            progressTag.put(taskId,30);
            for (int i = 0; i < insertList.size(); i++) {
                if (existOrgCodes.contains(insertList.get(i).getOrgCode())) {
                    insertList.remove(i);
                    i--;
                }
            }
            if (!CollectionUtils.isEmpty(insertList)) {
                villageDao.insertVillageOrgBatch(insertList);
                progressTag.put(taskId,60);
                //更新parentId
                //首先根据parentName聚合
                Map<String, List<OrganizationVillage>> parentNameMap = BeanMapUtil.mapList(insertList, "parentName");
                //再根据orgCode转成Map集合
                Map<String, OrganizationVillage> orgMap = BeanMapUtil.mapBean(insertList, "orgCode");
                for (Map.Entry<String, List<OrganizationVillage>> entry : parentNameMap.entrySet()) {
                    if (entry.getKey().equals("-1")) {
                        continue;
                    }
                    if (entry.getKey().equals("dbparent")) {
                        continue;
                    }
                    List<OrganizationVillage> sameParentOrgList = entry.getValue();
                    for (OrganizationVillage updateBean : sameParentOrgList) {
                        if (orgMap.get(String.valueOf(entry.getKey())) == null) {
                            throw new BusinessException(ExceptionCode.EQUIPMENT_VILLAGE_ORG_IMPORT_EXCEPTION_CODE,
                                    "找不到[" + entry.getKey() + "]自定义父节点");
                        }
                        updateBean.setParentId(orgMap.get(String.valueOf(entry.getKey())).getId());
                        villageDao.updateVillageOrgByPrimaryKey(updateBean);
                    }
                }
                progressTag.put(taskId,80);
                //新增角色关联的行政区划code
                for (OrganizationVillage insertBean : insertList) {
                    villageService.addRelRoleVillage(insertBean.getOrgCode());
                }
            }
            //正常的数据需要导入进去，错误的数据返回到Excel
            if (errorCount>0) {
                String errorFileName = exportExcelToLocal(taskId,fileName,headerTitle,dataListCopy);
                progressTag.put(taskId,100);
                return errorFileName;
            }
        } catch (Exception e) {
            if (e instanceof BusinessException) {
                throw new BusinessException(ExceptionCode.EQUIPMENT_VILLAGE_ORG_IMPORT_EXCEPTION_CODE, e.getMessage());
            } else {
                throw new BusinessException(ExceptionCode.EQUIPMENT_VILLAGE_ORG_IMPORT_EXCEPTION_CODE, "行政区划导入失败，保存数据库异常！");
            }
        }
        log.info("行政区划导入完成");
        progressTag.put(taskId, 100);
        return "";
    }

    @Override
    public int getImportDataProgress(String taskId) {
        return progressTag.get(taskId) == null ? 0 : progressTag.get(taskId);
    }
}
